<!DOCTYPE html>
<html>
<head>
    <title>Project4</title>
    <script src="d3.js" charset="utf-8"></script>
    <style>
    svg {font-family: Arial, sans-serif; }
    .area {fill-opacity: 0.8;}
    </style>
</head>
<body>
    <svg id="chart" width="880" height="800"></svg>
    <text id="text1"></text>
    <text id="text2"></text>
    <script>//实验三的图表重绘
    const chartdata = [
        { year: '2016', city: 3195, countryside: 1240 },
        { year: '2017', city: 3677, countryside: 1324 },
        { year: '2018', city: 4119, countryside: 1420 },
        { year: '2019', city: 4471, countryside: 1535 },
        { year: '2020', city: 2065, countryside: 814 },
        { year: '2021', city: 2342, countryside: 904 },
        { year: '2022', city: 1928, countryside: 601 }
    ];

    const chartmargin = { top: 100, right: 120, bottom: 170, left: 120 };
    const chartwidth = 880 - chartmargin.left - chartmargin.right;
    const chartheight = 800 - chartmargin.top - chartmargin.bottom;

    const chartsvg = d3.select("#chart")
        .attr("width", chartwidth + chartmargin.left + chartmargin.right)
        .attr("height", chartheight + chartmargin.top + chartmargin.bottom)
        .append("g")
        .attr("transform", `translate(${chartmargin.left}, ${chartmargin.top})`);

    const chartx = d3.scaleBand()//横轴映射时间
        .domain(chartdata.map(d => d.year))
        .range([0, chartwidth])
        .padding(0.2);

    const charty = d3.scaleLinear()//纵轴映射人数
        .domain([0, d3.max(chartdata, d => d.city + d.countryside)])
        .range([chartheight, 0]);

    const colors = d3.scaleOrdinal()//颜色比例尺
        .domain(['city', 'countryside'])
        .range(['#1f77b4', '#ff7f0e']);

    const stackGenerator = d3.stack()
        .keys(['city', 'countryside'])
        .order(d3.stackOrderNone)
        .offset(d3.stackOffsetNone);

    const stackData = stackGenerator(chartdata);

    chartsvg.selectAll(".series")
        .data(stackData)
        .join("g")
        .attr("class", "series")
        .attr("fill", d => colors(d.key))
        .selectAll("rect")
        .data(d => d)
        .join("rect")
        .attr("x", d => chartx(d.data.year))
        .attr("y", d => charty(d[1]))
        .attr("height", d => charty(d[0]) - charty(d[1]))
        .attr("width", chartx.bandwidth())

    chartsvg.selectAll(".series")//柱形的数值
        .selectAll("#text1")
        .data(d => d)
        .join("text")
        .attr("x", d => chartx(d.data.year) + chartx.bandwidth() / 2)
        .attr("y", d => charty(d[1]) - 5) 
        .attr("text-anchor", "middle")
        .attr("font-size", 14)
        .attr("fill", "black")
        .text(d => d[1]);

    chartsvg.selectAll(".series")//小矩形的数值
        .selectAll("#text2")
        .data(d => d)
        .join("text")
        .attr("x", d => chartx(d.data.year) + chartx.bandwidth() / 2)
        .attr("y", d => charty(d[0]/2+d[1]/2)+5)
        .attr("text-anchor", "middle")
        .attr("font-size", 12)
        .attr("fill", "black")
        .text(d => d[1]-d[0]);
        
    // 轴标题
    chartsvg.append("text")
        .attr("x", chartwidth / 2)
        .attr("y", -30)
        .attr("text-anchor", "middle")
        .attr("font-size",28)
        .text("疫情前后国内游客数变化");

    chartsvg.append("text")
        .attr("x", chartwidth / 2)
        .attr("y", chartheight + chartmargin.top - 40)
        .attr("text-anchor", "middle")
        .attr('font-size',22)
        .text("年份");

    chartsvg.append("text")
        .attr("transform", "rotate(-90)")
        .attr("x", -chartheight / 2)
        .attr("y", -chartmargin.left + 70)
        .attr("text-anchor", "middle")
        .attr('font-size',22)
        .text("国内游客数（百万人次）");

    // 轴坐标
    const xAxis = d3.axisBottom(chartx);
    const yAxis = d3.axisLeft(charty);

    chartsvg.append("g")
        .attr("transform", `translate(0, ${chartheight})`)
        .call(xAxis);

    chartsvg.append("g")
        .call(yAxis);

    //图例
    const chartlegend = chartsvg.append("g")
        .attr("transform", `translate(${chartwidth / 2}, ${chartheight + chartmargin.top + 40})`);

    const legendKeys = ['城镇居民游客', '农村居民游客'];
    const legendColor = d3.scaleOrdinal()
        .domain(legendKeys)
        .range(['#1f77b4', '#ff7f0e']);

    chartlegend.selectAll("rect")
        .data(legendKeys)
        .join("rect")
        .attr("x", (d, i) => i * 200 - 175)
        .attr("y", -50)
        .attr("width", 20)
        .attr("height", 15)
        .attr("fill", d => legendColor(d));

    chartlegend.selectAll("text")
        .data(legendKeys)
        .join("text")
        .attr('font-size',20)
        .attr("x", (d, i) => i * 200 - 145)
        .attr("y", -43)
        .attr("dy", "0.35em")
        .attr("text-anchor", "start")
        .text(d => d);
    </script>

    <svg id="stack-area" width="880" height="800"></svg>
    <script>//实验四堆叠图
    const data = [
        { day: 'Mon',  class: 8, selfstudy: 4, exercise: 0.5, sleep: 7, entertainment: 1 },
        { day: 'Tue', class: 10, selfstudy: 2, exercise: 1, sleep: 7, entertainment: 1 },
        { day: 'Wed', class: 6, selfstudy: 6, exercise: 1.5, sleep: 7, entertainment: 1.5 },
        { day: 'Thu', class: 6, selfstudy: 4, exercise: 1, sleep: 7, entertainment: 1.5 },
        { day: 'Fri', class: 2, selfstudy: 8, exercise: 0.5, sleep: 7, entertainment: 2 },
        { day: 'Sat', class: 0, selfstudy: 10, exercise: 1, sleep: 8, entertainment: 4 },
        { day: 'Sun', class: 3, selfstudy: 8, exercise: 0.5, sleep: 8, entertainment: 4 }
    ];

    const color = d3.scaleOrdinal()//颜色
        .domain(Object.keys(data[0]).filter(d => d !== 'day'))
        .range(d3.schemeSet3);

    const margin = { top: 170, right: 80, bottom: 220, left: 120 },
        width = 880 - margin.left - margin.right,
        height = 800 - margin.top - margin.bottom;

    const svg = d3.select("#stack-area")
        .append("svg")
        .append("g")
        .attr("transform", `translate(${margin.left},${margin.top})`);

    const x = d3.scaleBand()// X轴比例尺
        .domain(data.map(d => d.day))
        .range([0, width])
        .padding(-0.99);

    const y = d3.scaleLinear()// Y轴比例尺
        .domain([0, 24])
        .range([height, 0]);

    const stack = d3.stack()//堆叠
        .keys(Object.keys(data[0]).filter(d => d !== 'day'))
        .order(d3.stackOrderAscending)
        .offset(d3.stackOffsetNone);

    const area = d3.area()//区域
        .x(d => x(d.data.day) + x.bandwidth() / 2)
        .y0(d => y(d[0]))
        .y1(d => y(d[1]))
        .curve(d3.curveBasis);

    const layers = stack(data);//数据处理

    svg.selectAll("path")// 绘制区域
        .data(layers)
        .join("path")
        .attr("class", "area")
        .attr("fill", d => color(d.key))
        .attr("d", area);

    svg.append("g")// 添加X轴
        .attr("transform", `translate(0,${height})`)
        .call(d3.axisBottom(x));

    svg.append("g")// 添加Y轴
        .call(d3.axisLeft(y));

    svg.append("text")//标题
        .attr("x", width / 2)
        .attr("y", -30)
        .attr("text-anchor", "middle")
        .attr("font-size",28)
        .text("Daily Schedule");

    svg.append("text")//y轴标题
        .attr("transform", "rotate(-90)")
        .attr("x", -height / 2)
        .attr("y", -margin.left + 85)
        .attr("text-anchor", "middle")
        .attr('font-size',22)
        .text("Time(h)");

    // 图例
    const legend = svg.append("g")
        .attr("transform", `translate(${30},${height+50})`)
        .selectAll("g")
        .data(Object.keys(data[0]).filter(d => d !== 'day'))
        .join("g")
        .attr("transform", (d, i) => `translate(${i * 110},0)`);

    legend.append("rect")
        .attr("width", 18)
        .attr("height", 18)
        .attr("fill", color);

    legend.append("text")
        .attr("x", 23)
        .attr("y", 9)
        .attr("font-size",20)
        .attr("dy", "0.35em")
        .attr("text-anchor", "start")
        .text(d => d);
    </script>
</body>
</html>